package com.baidu.iit.pvm.runtime;

import com.baidu.iit.pvm.PvmException;
import com.baidu.iit.pvm.delegate.ExecutionListener;
import com.baidu.iit.pvm.process.ScopeImpl;

import java.util.List;

/**
 * 抽象流程执行器类，该类定义了流程调度中每个节点的behavior是怎么执行的
 * Created by 卫立 on 2014/4/7.
 */
public abstract class AbstractEventAtomicOperation implements AtomicOperation {

    /**
     * 是否是异步执行，这个接口留着为后续的性能优化使用
     * @param execution
     * @return
     */
    public boolean isAsync(InterpretableExecution execution) {
        return false;
    }

    /**
     * 事件调度器的调度执行函数
     * @param execution
     */
    public void execute(InterpretableExecution execution) {
        //获取要执行的单元，或者是节点根据上下问分析
        ScopeImpl scope = getScope(execution);
        //获取单元相关的监听事件，根据调度器所处的事件获取
        List<ExecutionListener> exectionListeners = scope.getExecutionListeners(getEventName());

        //获取当前的执行节点的值，默认为0
        int executionListenerIndex = execution.getExecutionListenerIndex();

        //这里采用递归调用的方式执行监听器
        if (exectionListeners.size() > executionListenerIndex) {
            execution.setEventName(getEventName());
            execution.setEventSource(scope);
            ExecutionListener listener = exectionListeners.get(executionListenerIndex);
            try {
                listener.notify(execution);
            } catch (RuntimeException e) {
                throw e;
            } catch (Exception e) {
                throw new PvmException("不能执行相关的事件监听器 : " + e.getMessage(), e);
            }


            //增加调度的次数
            execution.setExecutionListenerIndex(executionListenerIndex + 1);

            //调用当前流程的操作函数
            execution.performOperation(this);
        } else {
            //事件调用结束，重置事件调度顺序
            execution.setExecutionListenerIndex(0);
            //重置事件名称
            execution.setEventName(null);
            //重置事件源
            execution.setEventSource(null);
            //通知完成当前的任务
            eventNotificationsCompleted(execution);
        }
    }

    /**
     * 获取执行单元
     * @param execution
     * @return
     */
    protected abstract ScopeImpl getScope(InterpretableExecution execution);

    /**
     * 获取事件的名称
     * @return
     */
    protected abstract String getEventName();

    /**
     * 事件是否通知完毕的信息
     * @param execution
     */
    protected abstract void eventNotificationsCompleted(InterpretableExecution execution);
}